<template>
	<view class="tui-sticky-class">
		<!--sticky 容器-->
		<view v-if="isFixed" :style="{ height: stickyHeight, backgroundColor: backgroundColor }"></view>

		<view :class="{ 'tui-sticky-fixed': isFixed }" :style="{ top: isFixed ? stickyTop + 'px' : 'auto' }"><slot name="header"></slot></view>
		<!--sticky 容器-->

		<!--内容-->
		<slot name="content"></slot>
	</view>
</template>

<script setup>
import { ref, reactive, toRefs, watch, getCurrentInstance, onBeforeMount, onMounted } from 'vue'

const { ctx } = getCurrentInstance()

const emit = defineEmits(['sticky', 'change'])

const props = defineProps({
	scrollTop: {
		type: Number
	},
	//吸顶时与顶部的距离，单位px
	stickyTop: {
		type: [Number, String],
		// #ifndef H5
		default: 0,
		// #endif

		// #ifdef H5
		default: 44
		// #endif
	},
	//是否指定容器，即内容放置插槽content内
	container: {
		type: Boolean,
		default: false
	},
	//是否是原生自带header
	isNativeHeader: {
		type: Boolean,
		default: true
	},
	//吸顶容器 高度 rpx
	stickyHeight: {
		type: String,
		default: '80rpx'
	},
	//占位容器背景颜色
	backgroundColor: {
		type: String,
		default: 'transparent'
	},
	//是否重新计算[有异步加载时使用,设置大于0的数]
	recalc: {
		type: Number,
		default: 0
	},
	//列表中的索引值
	index: {
		type: [Number, String],
		default: 0
	}
})

let timer = null
let initialize = 0
let top = 0
let height = 0

const state = reactive({
	isFixed: false
})

watch(
	() => props.scrollTop,
	nVal => {
		if (initialize != 0) {
			updateScrollChange(() => {
				updateStickyChange()
				initialize = 0
			})
		} else {
			updateStickyChange()
		}
	}
)

watch(
	() => props.recalc,
	nVal => {
		updateScrollChange(() => {
			updateStickyChange()
			initialize = 0
		})
	}
)

onBeforeMount(() => {
	initialize = props.recalc
})

onMounted(() => {
	setTimeout(() => {
		updateScrollChange()
	}, 20)
})

const updateStickyChange = () => {
	const scrollTop = props.scrollTop
	let stickyTop = props.stickyTop

	// #ifdef H5
	if (this.isNativeHeader) {
		stickyTop = stickyTop - 44
		stickyTop = stickyTop < 0 ? 0 : stickyTop
	}
	// #endif

	if (props.container) {
		state.isFixed = scrollTop + stickyTop >= top && scrollTop + stickyTop < top + height ? true : false
	} else {
		state.isFixed = scrollTop + stickyTop >= top ? true : false
	}

	//是否吸顶
	emit('sticky', {
		isFixed: state.isFixed,
		index: Number(props.index)
	})
}

const updateScrollChange = callback => {
	if (timer) {
		clearTimeout(timer)
		timer = null
	}

	timer = setTimeout(() => {
		const className = '.tui-sticky-class'
		const query = uni
			.createSelectorQuery()
			// #ifndef MP-ALIPAY
			.in(ctx)
		// #endif

		query
			.select(className)
			.boundingClientRect(res => {
				if (res) {
					//bottom: 168,height: 80,left: 0,right: 375,top: 88,width: 375
					console.log('boundingClientRect: ', res)
					top = res.top + (props.scrollTop || 0)
					height = res.height
					callback && callback()
					emit('change', {
						index: Number(props.index),
						top
					})
				}
			})
			.exec()
	}, 0)
}

const { isFixed } = toRefs(state)
</script>

<style lang="scss" scoped>
.tui-sticky-fixed {
	width: 100%;
	position: fixed;
	left: 0;
	z-index: 888;
}
</style>
